﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Data.SugarClient.Soap.V1;

namespace System.Data.SugarClient
{

	public class SugarRestContext
	{

		internal SugarRestContext(
			string url)
		{
			this.Url = url;
		}

		#region Fields

		private string _url;
		private string _session = string.Empty;

		#endregion 

		#region Properties

		protected internal string Session
		{
			get { return this._session; }
		}

		//internal int Timeout
		//{
		//  get { return this._soapV1.Timeout; }
		//  set { this._soapV1.Timeout = value; }
		//}

		internal string Url
		{
			get { return this._url; }
			set
			{
				if (this.Url == value) return;
				this._url = value;
				this.OnUrlChanged(new EventArgs());
			}
		}

		internal string RestEndPoint
		{
			get { return this.GetRestUrl(2); }
		}

		#endregion

		#region Methods

		protected void OnUrlChanged(EventArgs e)
		{
			// this._soapV1.Url = this.GetSoapUrl(1);
			// this._soapV2.Url = this.GetSoapUrl(2);
		}

		public void Login(string username, string password)
		{
			this.Login(username, password, string.Empty);
		}

		internal void Login(string username, string password, string encryptionkey)
		{
			SugarRestActionResult result = this.ExecuteAction<SugarRestActionResult>(SugarRestActionType.Login, username, password, encryptionkey);
			//if (result.Success) this._session = result.SessionId;
			//else throw new SugarException(string.Format("Can not login to Sugar instance. {0}", result.RawResult.error.description));
		}

		internal TResult ExecuteAction<TResult>(
			SugarRestActionType type,
			params object[] args) where TResult : SugarRestActionResult
		{
			return this.ExecuteAction(type, args) as TResult;
		}

		internal SugarRestActionResult ExecuteAction(
			SugarRestActionType type,
			params object[] args)
		{
			return this.CreateAction(type, args).Execute();
		}

		internal SugarRestAction CreateAction(
			SugarRestActionType type,
			params object[] args)
		{
			return CreateAction(type, DetectVersion(), args);
		}

		internal SugarRestAction CreateAction(
			SugarRestActionType type,
			int apiversion,
			params object[] args)
		{
			switch (type)
			{
				case SugarRestActionType.Login: return CreateLoginAction(apiversion, args);
			}
			throw new NotImplementedException();
		}

		#region CreateXXXAction

		internal SugarRestAction CreateLoginAction(
			int apiversion,
			params object[] args)
		{
			switch (apiversion)
			{
				case 2: return CreateV2LoginAction(args);
			}
			throw new NotImplementedException();
		}

		#endregion

		internal SugarRestAction CreateV2LoginAction(
			params object[] args)
		{
			return new SugarRestAction(this.RestEndPoint, SugarRestAction.CreateActionParam(SugarRestActionType.Login, 2, args));
		}

		protected int DetectVersion()
		{
			return 2;
		}

		protected string GetValidSessionIdOrThrow()
		{
			if (string.IsNullOrEmpty(this.Session)) throw new SugarException("Login First!");
			else return this._session;
		}

		protected string GetRestUrl(int apiversion)
		{
			string format = (this.Url.EndsWith("/")) ? "" : this.Url + "/";
			switch(apiversion)
			{
				case 2: format += "{0}service/v2/rest.php"; break;
				default: throw new NotImplementedException();
			}
			return string.Format(format, this.Url);
		}

		#endregion

	}
}